<template>
  <nav-bar />
  <view class="notice-page">
    <!-- 顶部导航 -->
    <view class="nav-bar">
      <text class="nav-back" @click="onBack">&#8592;</text>
      <text class="nav-title">公告列表</text>
      <text class="nav-add" @click="onAddNotice" v-if="canEdit">+</text>
    </view>

    <!-- 搜索和筛选区域 -->
    <view class="search-filter">
      <view class="search-box">
        <text class="search-icon">🔍</text>
        <input 
          type="text" 
          v-model="searchKeyword" 
          placeholder="搜索公告标题" 
          class="search-input"
        />
        <text class="clear-icon" @click="clearSearch" v-if="searchKeyword">×</text>
      </view>
      <view class="filter-box">
        <view class="filter-item" :class="{ active: filterDate }" @click="showDatePicker">
          <text class="filter-icon">📅</text>
          <text class="filter-text">{{ filterDate || '日期筛选' }}</text>
          <text class="clear-filter" @click.stop="clearFilter" v-if="filterDate">×</text>
        </view>
      </view>
    </view>

    <!-- 日期选择器弹窗 -->
    <uni-popup ref="datePickerPopup" type="bottom">
      <view class="date-picker-popup">
        <view class="popup-header">
          <text class="popup-title">选择日期</text>
          <text class="popup-close" @click="closeDatePicker">×</text>
        </view>
        <picker-view 
          class="picker-view" 
          :value="pickerValue" 
          @change="onPickerChange"
        >
          <picker-view-column>
            <view class="picker-item" v-for="(year, index) in years" :key="'year-'+index">
              {{ year }}年
            </view>
          </picker-view-column>
          <picker-view-column>
            <view class="picker-item" v-for="(month, index) in months" :key="'month-'+index">
              {{ month }}月
            </view>
          </picker-view-column>
          <picker-view-column>
            <view class="picker-item" v-for="(day, index) in days" :key="'day-'+index">
              {{ day }}日
            </view>
          </picker-view-column>
        </picker-view>
        <view class="popup-footer">
          <button class="cancel-btn" @click="closeDatePicker">取消</button>
          <button class="today-btn" @click="selectToday">今天</button>
          <button class="confirm-btn" @click="confirmDate">确定</button>
        </view>
      </view>
    </uni-popup>

    <!-- 公告列表 -->
    <scroll-view class="notice-list" scroll-y>
      <view class="notice-item" v-for="notice in filteredNoticeList" :key="notice.notice_id" @click="viewNotice(notice)">
        <view class="notice-header">
          <text class="notice-title">{{ notice.notice_title }}</text>
          <text class="notice-time">{{ notice.create_time }}</text>
        </view>
        <text class="notice-content">{{ notice.notice_content }}</text>
        <view class="notice-images" v-if="notice.notice_image && notice.notice_image.length > 0">
          <view class="image-grid">
            <view class="image-item" v-for="(img, index) in notice.notice_image" :key="index" @click="previewImage(notice.notice_image, index)">
              <image :src="IntranetConfig.domain + img.image" mode="aspectFill" class="notice-image" />
            </view>
          </view>
        </view>
        <view class="notice-footer">
          <text class="notice-publisher">发布人：{{ notice.notice_publisher }}</text>
        </view>
      </view>
    </scroll-view>

    <!-- 添加/编辑公告弹窗 -->
    <uni-popup ref="noticePopup" type="center">
      <view class="notice-popup">
        <view class="popup-header">
          <text class="popup-title">{{ isEdit ? '编辑公告' : '添加公告' }}</text>
          <text class="popup-close" @click="closeNoticePopup">×</text>
        </view>
        <view class="popup-content">
          <view class="form-item required">
            <view class="label">标题</view>
            <input class="value-input" v-model="form.notice_title" placeholder="请输入" maxlength="50" :disabled="!canEdit" />
          </view>
          <view class="form-item required">
            <view class="label">内容</view>
            <textarea 
              class="value-textarea" 
              v-model="form.notice_content" 
              placeholder="请输入公告内容"
              :maxlength="1000"
              show-confirm-bar="false"
              :disabled="!canEdit"
            />
            <view class="word-count">{{ form.notice_content.length }}/1000</view>
          </view>
          <view class="form-item">
            <view class="label">图片</view>
            <view class="image-upload">
              <view class="image-grid">
                <!-- 已存在图片 -->
                <view class="image-item" v-for="(img, index) in form.existImages" :key="'exist-' + img.id">
                  <image :src="img.url" mode="aspectFill" class="preview-image" @click="previewExistImage(index)" />
                  <view class="delete-btn" @click.stop="deleteExistImage(img, index)" v-if="canEdit">×</view>
                </view>
                <!-- 新选图片 -->
                <view class="image-item" v-for="(img, index) in form.images" :key="'new-' + index">
                  <image :src="img" mode="aspectFill" class="preview-image" @click="previewNewImage(index)" />
                  <view class="delete-btn" @click.stop="deleteImage(index)" v-if="canEdit">×</view>
                </view>
                <view class="add-image" @click="chooseImage" v-if="canEdit && (form.images.length + form.existImages.length < 9)">
                  <text class="add-icon">+</text>
                </view>
              </view>
            </view>
          </view>
        </view>
        <view class="popup-footer">
          <button class="cancel-btn" @click="closeNoticePopup">取消</button>
          <button class="confirm-btn" @click="saveNotice" :disabled="!canEdit">确定</button>
        </view>
      </view>
    </uni-popup>

    <!-- 查看公告弹窗 -->
    <uni-popup ref="viewPopup" type="center">
      <view class="notice-popup view-popup">
        <view class="popup-header">
          <text class="popup-title">公告详情</text>
          <text class="popup-close" @click="closeViewPopup">×</text>
        </view>
        <scroll-view class="popup-content" scroll-y>
          <view class="notice-detail">
            <view class="detail-header">
              <text class="detail-title">{{ currentNotice.notice_title }}</text>
              <view class="detail-meta">
                <text class="detail-publisher">发布人：{{ currentNotice.notice_publisher }}</text>
                <text class="detail-time">{{ currentNotice.create_time }}</text>
          </view>
          </view>
            <view class="detail-content">
              <text class="content-text">{{ currentNotice.notice_content }}</text>
            </view>
            <view class="detail-images" v-if="currentNotice.notice_image && currentNotice.notice_image.length > 0">
            <view class="image-grid">
              <view class="image-item" v-for="(img, index) in currentNotice.notice_image" :key="index">
                <image :src="IntranetConfig.domain + img.image" mode="aspectFill" class="preview-image" @click="previewImage(currentNotice.notice_image, index)" />
                <view class="delete-btn" @click.stop="deleteNoticeImage(currentNotice.notice_id, img.id)" v-if="canEdit">×</view>
              </view>
            </view>
          </view>
          </view>
        </scroll-view>
        <view class="popup-footer">
          <button class="close-btn" @click="closeViewPopup">关闭</button>
          <view class="dropdown-menu" v-if="canEdit">
            <button class="dropdown-trigger" @click="toggleDropdown">更多操作</button>
            <view class="dropdown-content" v-show="showDropdown">
              <button class="dropdown-item" @click="editNotice">编辑</button>
              <button class="dropdown-item" @click="deleteNotice">删除</button>
          </view>
        </view>
        </view>
      </view>
    </uni-popup>

    <!-- 自定义消息框组件 -->
    <message-box
      v-model="showMsgBox"
      :title="msgBoxTitle"
      :content="msgBoxContent"
      :showCancel="msgBoxShowCancel"
      :confirmText="msgBoxConfirmText"
      :cancelText="msgBoxCancelText"
      @confirm="onMsgBoxConfirm"
      @cancel="onMsgBoxCancel"
    />

    <!-- 自定义 Toast 组件 -->
    <toast
      v-model="showToast"
      :content="toastContent"
      :type="toastType"
      :duration="toastDuration"
    />
  </view>
  </template>
  
  <script setup>
import { ref, onMounted, computed } from 'vue'
import { IntranetConfig, UserConfig } from '@/static/js/config'
import MessageBox from '@/components/message-box/message-box.vue'
import Toast from '@/components/toast/toast.vue'

// 获取用户信息
const userInfo = computed(() => UserConfig.getUserInfo())

// Toast 相关
const showToast = ref(false)
const toastContent = ref('')
const toastType = ref('')
const toastDuration = ref(2000)

function showCustomToast(content, type = '', duration = 2000) {
  toastContent.value = content
  toastType.value = type
  toastDuration.value = duration
  showToast.value = true
}

// 消息框相关
const showMsgBox = ref(false)
const msgBoxTitle = ref('')
const msgBoxContent = ref('')
const msgBoxShowCancel = ref(true)
const msgBoxConfirmText = ref('确定')
const msgBoxCancelText = ref('取消')
let msgBoxCallback = null

function openMsgBox({ title = '', content = '', showCancel = true, confirmText = '确定', cancelText = '取消', callback = null }) {
  msgBoxTitle.value = title
  msgBoxContent.value = content
  msgBoxShowCancel.value = showCancel
  msgBoxConfirmText.value = confirmText
  msgBoxCancelText.value = cancelText
  msgBoxCallback = callback
  showMsgBox.value = true
}

function onMsgBoxConfirm() {
  if (msgBoxCallback) msgBoxCallback(true)
}

function onMsgBoxCancel() {
  if (msgBoxCallback) msgBoxCallback(false)
}

// 公告列表数据
const noticeList = ref([])
const noticePopup = ref(null)
const viewPopup = ref(null)
const isEdit = ref(false)
const currentNotice = ref({})

// 表单数据
const form = ref({
  notice_title: '',
  notice_content: '',
  images: [],
  existImages: []
})

// 搜索和筛选相关
const searchKeyword = ref('')
const filterDate = ref('')

// 日期选择器相关
const datePickerPopup = ref(null)
const pickerValue = ref([0, 0, 0])
const years = ref([])
const months = ref(Array.from({length: 12}, (_, i) => i + 1))
const days = ref([])
const tempDate = ref('')

// 添加下拉菜单状态控制
const showDropdown = ref(false)

// 切换下拉菜单显示状态
function toggleDropdown() {
  showDropdown.value = !showDropdown.value
}

// 初始化日期选择器数据
function initDatePicker() {
  const currentYear = new Date().getFullYear()
  years.value = Array.from({length: 5}, (_, i) => currentYear - 2 + i)
  updateDays()
}

// 更新天数
function updateDays() {
  const year = years.value[pickerValue.value[0]]
  const month = months.value[pickerValue.value[1]]
  const daysInMonth = new Date(year, month, 0).getDate()
  days.value = Array.from({length: daysInMonth}, (_, i) => i + 1)
}

// 显示日期选择器
function showDatePicker() {
  if (filterDate.value) {
    const [year, month, day] = filterDate.value.split('-')
    pickerValue.value = [
      years.value.indexOf(parseInt(year)),
      months.value.indexOf(parseInt(month)),
      days.value.indexOf(parseInt(day))
    ]
  }
  datePickerPopup.value.open()
}

// 关闭日期选择器
function closeDatePicker() {
  datePickerPopup.value.close()
}

// 日期选择器值改变
function onPickerChange(e) {
  pickerValue.value = e.detail.value
  updateDays()
}

// 确认日期选择
function confirmDate() {
  const year = years.value[pickerValue.value[0]]
  const month = months.value[pickerValue.value[1]]
  const day = days.value[pickerValue.value[2]]
  filterDate.value = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`
  closeDatePicker()
}

// 清除搜索
function clearSearch() {
  searchKeyword.value = ''
}

// 清除筛选
function clearFilter() {
  filterDate.value = ''
}

// 筛选后的公告列表
const filteredNoticeList = computed(() => {
  let result = [...noticeList.value]
  
  // 按关键词搜索
  if (searchKeyword.value) {
    const keyword = searchKeyword.value.toLowerCase()
    result = result.filter(notice => 
      notice.notice_title.toLowerCase().includes(keyword) ||
      notice.notice_content.toLowerCase().includes(keyword)
    )
  }
  
  // 按日期筛选
  if (filterDate.value) {
    result = result.filter(notice => {
      const noticeDate = notice.create_time.split(' ')[0]
      return noticeDate === filterDate.value
    })
  }
  
  return result
})

// 计算属性：是否可以编辑
const canEdit = computed(() => {
  return userInfo.value && (userInfo.value.is_superuser === 1 || userInfo.value.is_superuser === 2)
})

// 获取公告列表
async function getNoticeList() {
  try {
    const res = await uni.request({
      url: IntranetConfig.domain + 'api/notice/get_notice_list/',
      method: 'GET',
      header: IntranetConfig.headers
    })

    if (res.data.code === 200) {
      noticeList.value = res.data.data
    } else {
      throw new Error(res.data.msg)
    }
  } catch (error) {
    showCustomToast(error.message || '获取公告列表失败', 'error')
  }
}

// 返回上一页
function onBack() {
  uni.navigateBack()
}

// 添加公告
function onAddNotice() {
  if (!canEdit.value) return
  isEdit.value = false
  form.value = {
    notice_title: '',
    notice_content: '',
    images: [],
    existImages: []
  }
  noticePopup.value.open()
}

// 查看公告
function viewNotice(notice) {
  const loadingToast = uni.showLoading({
    title: '加载中...',
    mask: true
  });

  uni.request({
    url: IntranetConfig.domain + `api/notice/get_notice/${notice.notice_id}/`,
    method: 'GET',
    header: IntranetConfig.headers,
    success: (res) => {
      if (res.data.code === 200) {
        currentNotice.value = res.data.data;
        viewPopup.value.open();
      } else {
        showCustomToast(res.data.msg || '获取公告详情失败', 'error');
      }
    },
    fail: () => {
      showCustomToast('获取公告详情失败', 'error');
    },
    complete: () => {
      uni.hideLoading();
    }
  });
}

// 编辑公告
function editNotice() {
  if (!canEdit.value) return
  showDropdown.value = false
  isEdit.value = true
  form.value = {
    notice_title: currentNotice.value.notice_title,
    notice_content: currentNotice.value.notice_content,
    images: [],
    existImages: (currentNotice.value.notice_image || []).map(img => ({ id: img.id, url: IntranetConfig.domain + img.image }))
  }
  viewPopup.value.close()
  noticePopup.value.open()
}

// 删除公告
function deleteNotice() {
  if (!canEdit.value) return
  showDropdown.value = false
  openMsgBox({
    title: '确认删除',
    content: '确定要删除这条公告吗？',
    showCancel: true,
    confirmText: '确定',
    cancelText: '取消',
    callback: async (confirmed) => {
      if (confirmed) {
        try {
          const res = await uni.request({
            url: IntranetConfig.domain + `api/notice/delete_notice/${currentNotice.value.notice_id}/`,
            method: 'DELETE',
            header: IntranetConfig.headers
          })

          if (res.data.code === 200) {
            showCustomToast('删除成功', 'success')
            viewPopup.value.close()
            getNoticeList()
          } else {
            throw new Error(res.data.msg)
          }
        } catch (error) {
          showCustomToast(error.message || '删除失败', 'error')
        }
      }
    }
  })
}

// 选择图片
function chooseImage() {
  uni.chooseImage({
    count: 9 - form.value.images.length - form.value.existImages.length,
    success: (res) => {
      form.value.images = [...form.value.images, ...res.tempFilePaths]
    }
  })
}

// 删除图片
function deleteImage(index) {
  form.value.images.splice(index, 1)
}

// 关闭弹窗
function closeNoticePopup() {
  noticePopup.value.close()
}

function closeViewPopup() {
  showDropdown.value = false
  viewPopup.value.close()
}

// 保存公告
async function saveNotice() {
  if (!canEdit.value) return
  if (!form.value.notice_title) {
    showCustomToast('请输入公告标题', 'error')
    return
  }
  if (!form.value.notice_content) {
    showCustomToast('请输入公告内容', 'error')
    return
  }

  uni.showLoading({
    title: '保存中...',
    mask: true
  })

  try {
    // 构建请求数据
    const requestData = {
      notice_title: form.value.notice_title,
      notice_content: form.value.notice_content,
      notice_publisher: userInfo.value.id
    }

    // 创建或更新公告
    const url = isEdit.value 
      ? `api/notice/update_notice/${currentNotice.value.notice_id}/`
      : 'api/notice/create_notice/'
    
    const res = await uni.request({
      url: IntranetConfig.domain + url,
      method: 'POST',
      header: IntranetConfig.headers,
      data: requestData
    })

    if (res.data.code === 200) {
      const noticeId = isEdit.value ? currentNotice.value.notice_id : res.data.data.notice_id

      // 如果有图片，上传图片
      if (form.value.images.length > 0) {
        // 使用 Promise.all 处理所有图片上传
        const uploadPromises = form.value.images.map(imagePath => {
          return new Promise((resolve, reject) => {
            const uploadTask = uni.uploadFile({
              url: IntranetConfig.domain + `api/notice/upload_notice_image/${noticeId}/`,
              filePath: imagePath,
              fileType: 'image',
              name: 'image',
              formData: {
                notice: noticeId.toString()
              },
              success: (res) => {
                try {
                  const data = JSON.parse(res.data)
                  if (data.code === 200) {
                    resolve(data)
                  } else {
                    reject(new Error(data.msg))
                  }
                } catch (e) {
                  reject(new Error('解析响应数据失败'))
                }
              },
              fail: (err) => {
                reject(new Error(err.errMsg || '上传失败'))
              }
            })

            // 监听上传进度
            uploadTask.onProgressUpdate((res) => {
              console.log('上传进度：', res.progress)
            })
          })
        })

        try {
          await Promise.all(uploadPromises)
          showCustomToast(isEdit.value ? '更新成功' : '添加成功', 'success')
        } catch (error) {
          console.error('图片上传错误：', error)
          showCustomToast('公告已保存，但图片上传失败', 'error', 2000)
        }
      } else {
        showCustomToast(isEdit.value ? '更新成功' : '添加成功', 'success')
      }

      closeNoticePopup()
      getNoticeList()
    } else {
      throw new Error(res.data.msg)
    }
  } catch (error) {
    console.error('保存公告错误：', error)
    showCustomToast(error.message || (isEdit.value ? '更新失败' : '添加失败'), 'error')
  } finally {
    uni.hideLoading()
  }
}

// 删除公告图片
function deleteNoticeImage(noticeId, imageId) {
  if (!canEdit.value) return
  openMsgBox({
    title: '确认删除',
    content: '确定要删除这张图片吗？',
    showCancel: true,
    confirmText: '确定',
    cancelText: '取消',
    callback: async (confirmed) => {
      if (confirmed) {
        const loadingToast = uni.showLoading({
          title: '删除中...',
          mask: true
        });

        try {
          const res = await uni.request({
            url: IntranetConfig.domain + `api/notice/delete_notice_image/${imageId}/`,
            method: 'DELETE',
            header: IntranetConfig.headers
          });

          if (res.data.code === 200) {
            showCustomToast('删除成功', 'success');
            // 重新获取公告详情
            viewNotice({ notice_id: noticeId });
          } else {
            throw new Error(res.data.msg);
          }
        } catch (error) {
          showCustomToast(error.message || '删除失败', 'error');
        } finally {
          uni.hideLoading();
        }
      }
    }
  });
}

// 预览图片
function previewImage(images, current) {
  const urls = images.map(img => IntranetConfig.domain + (img.image || img));
  uni.previewImage({
    urls,
    current: urls[current],
    indicator: 'number',
    loop: true
  });
}

// 预览已存在图片
function previewExistImage(index) {
  const urls = form.value.existImages.map(img => img.url)
  uni.previewImage({
    urls,
    current: urls[index],
    indicator: 'number',
    loop: true
  })
}

// 预览新选图片
function previewNewImage(index) {
  uni.previewImage({
    urls: form.value.images,
    current: form.value.images[index],
    indicator: 'number',
    loop: true
  })
}

// 删除已存在图片
async function deleteExistImage(img, index) {
  if (!canEdit.value) return
  openMsgBox({
    title: '确认删除',
    content: '确定要删除这张图片吗？',
    showCancel: true,
    confirmText: '确定',
    cancelText: '取消',
    callback: async (confirmed) => {
      if (confirmed) {
        uni.showLoading({ title: '删除中...', mask: true })
        try {
          const res = await uni.request({
            url: IntranetConfig.domain + `api/notice/delete_notice_image/${img.id}/`,
            method: 'DELETE',
            header: IntranetConfig.headers
          })
          if (res.data.code === 200) {
            form.value.existImages.splice(index, 1)
            showCustomToast('删除成功', 'success')
          } else {
            throw new Error(res.data.msg)
          }
        } catch (error) {
          showCustomToast(error.message || '删除失败', 'error')
        } finally {
          uni.hideLoading()
        }
      }
    }
  })
}

// 选择今天
function selectToday() {
  const now = new Date();
  const year = now.getFullYear();
  const month = now.getMonth() + 1;
  const day = now.getDate();
  // 定位picker
  pickerValue.value = [
    years.value.indexOf(year),
    months.value.indexOf(month),
    days.value.indexOf(day)
  ];
  filterDate.value = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
  closeDatePicker();
}

// 页面加载
onMounted(() => {
  getNoticeList()
  initDatePicker()
})
  </script>
  
  <style lang="scss" scoped>
.notice-page {
  background: #f8f9fa;
  min-height: 100vh;
  font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
}

.nav-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 32rpx;
  height: 96rpx;
  background: #fff;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
  position: sticky;
  top: 0;
  z-index: 100;
  
  .nav-back { 
    color: #333; 
    font-size: 44rpx;
    width: 80rpx;
    height: 80rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    transition: all 0.3s;
    
    &:active {
      background: rgba(0, 0, 0, 0.05);
    }
  }
  
  .nav-title { 
    flex: 1; 
    text-align: center; 
    font-size: 36rpx;
    font-weight: 600;
    color: #333;
  }

  .nav-add {
    color: #ff7e2d;
    font-size: 44rpx;
    width: 80rpx;
    height: 80rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    transition: all 0.3s;
    
    &:active {
      background: rgba(255, 126, 45, 0.1);
    }
  }
}

.search-filter {
  padding: 16rpx 24rpx;
  background: #fff;
  border-bottom: 1rpx solid #f5f5f5;
  display: flex;
  gap: 16rpx;
  align-items: center;
  
  .search-box {
    flex: 1;
    position: relative;
    height: 72rpx;
    background: #f8f9fa;
    border-radius: 36rpx;
    display: flex;
    align-items: center;
    padding: 0 24rpx;
    border: 1rpx solid #eee;
    
    .search-icon {
      font-size: 32rpx;
      color: #999;
      margin-right: 12rpx;
    }
    
    .search-input {
      flex: 1;
      height: 100%;
      font-size: 28rpx;
      color: #333;
      
      &::placeholder {
        color: #999;
      }
    }
    
    .clear-icon {
      font-size: 32rpx;
      color: #999;
      padding: 8rpx;
      margin: -8rpx;
      border-radius: 50%;
      
      &:active {
        background: rgba(0, 0, 0, 0.05);
      }
    }
  }
  
  .filter-box {
    .filter-item {
      height: 72rpx;
      background: #f8f9fa;
      border-radius: 36rpx;
      display: flex;
      align-items: center;
      padding: 0 24rpx;
      border: 1rpx solid #eee;
      gap: 8rpx;
      
      &.active {
        background: #fff6ed;
        border-color: #ff7e2d;
        
        .filter-icon,
        .filter-text {
          color: #ff7e2d;
        }
      }
      
      .filter-icon {
        font-size: 32rpx;
        color: #999;
      }
      
      .filter-text {
        font-size: 28rpx;
        color: #666;
        max-width: 160rpx;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      
      .clear-filter {
        font-size: 32rpx;
        color: #999;
        padding: 8rpx;
        margin: -8rpx;
        border-radius: 50%;
        
        &:active {
          background: rgba(0, 0, 0, 0.05);
        }
      }
    }
  }
}

.notice-list {
  padding: 24rpx;
  height: calc(100vh - 96rpx - 200rpx);
  box-sizing: border-box;
}

.notice-item {
  background: #fff;
  border-radius: 24rpx;
  padding: 32rpx;
  margin-bottom: 24rpx;
  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
  
  .notice-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16rpx;
    
    .notice-title {
      font-size: 32rpx;
      font-weight: 600;
      color: #333;
    }
    
    .notice-time {
      font-size: 24rpx;
      color: #999;
    }
  }
  
  .notice-content {
    font-size: 28rpx;
    color: #666;
    line-height: 1.6;
    margin-bottom: 24rpx;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
  }
  
  .notice-images {
    margin: 16rpx 0;
  }
  
  .notice-footer {
    display: flex;
    justify-content: flex-end;
    
    .notice-publisher {
      font-size: 24rpx;
      color: #999;
    }
  }
}

.image-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16rpx;
  width: 100%;
  box-sizing: border-box;
}

.image-item {
  position: relative;
  width: 100%;
  padding-bottom: 100%;
  border-radius: 16rpx;
  overflow: hidden;
  background: #f8f9fa;
  
  .notice-image,
  .preview-image {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}

.notice-popup {
  width: 90vw;
  max-width: 600rpx;
  background: #fff;
  border-radius: 24rpx;
  overflow: hidden;
  
  .popup-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 32rpx;
    border-bottom: 1rpx solid #f5f5f5;
    
    .popup-title {
      font-size: 32rpx;
      font-weight: 600;
      color: #333;
    }
    
    .popup-close {
      font-size: 40rpx;
      color: #999;
      padding: 16rpx;
      margin: -16rpx;
      border-radius: 50%;
      transition: all 0.3s;
      
      &:active {
        background: #f5f5f5;
      }
    }
  }
  
  .popup-content {
    padding: 32rpx;
    max-height: 60vh;
    overflow-y: auto;
    box-sizing: border-box;
    
    .form-item {
      margin-bottom: 32rpx;
      width: 100%;
      box-sizing: border-box;
      
      .label {
        font-size: 28rpx;
        color: #333;
        margin-bottom: 16rpx;
        font-weight: 500;
      }
      
      .value-input {
        width: 100%;
        height: 80rpx;
        background: #f8f9fa;
        border-radius: 16rpx;
        padding: 0 24rpx;
        font-size: 28rpx;
        color: #333;
        border: 1rpx solid #eee;
        box-sizing: border-box;
        
        &::placeholder {
          color: #999;
        }
      }
      
      .value-textarea {
        width: 100%;
        height: 300rpx;
        background: #f8f9fa;
        border-radius: 16rpx;
        padding: 24rpx;
        font-size: 28rpx;
        color: #333;
        border: 1rpx solid #eee;
        box-sizing: border-box;
        
        &::placeholder {
          color: #999;
        }
      }
      
      .word-count {
        text-align: right;
        font-size: 24rpx;
        color: #999;
        margin-top: 8rpx;
      }
    }
    
    .image-upload {
      width: 100%;
      box-sizing: border-box;
    }
  }
  
  .popup-footer {
    padding: 24rpx 32rpx;
    border-top: 1rpx solid #f0f0f0;
    background: #fff;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 24rpx;
    
    .close-btn {
      flex: 1;
      height: 88rpx;
      border: none;
      border-radius: 12rpx;
      font-size: 32rpx;
      font-weight: 500;
      background: #f5f5f5;
      color: #666;
      transition: all 0.3s;
      
      &:active {
        transform: scale(0.98);
        background: darken(#f5f5f5, 5%);
      }
    }
    
    .dropdown-menu {
      flex: 1;
      position: relative;
      
      .dropdown-trigger {
        width: 100%;
        height: 88rpx;
        border: none;
        border-radius: 12rpx;
        font-size: 32rpx;
        font-weight: 500;
        background: #ff7e2d;
        color: #fff;
        transition: all 0.3s;
      
      &:active {
          transform: scale(0.98);
          background: darken(#ff7e2d, 5%);
      }
    }
    
      .dropdown-content {
        position: absolute;
        right: 0;
        bottom: 100%;
        margin-bottom: 8rpx;
        background: #fff;
        border-radius: 12rpx;
        box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
        min-width: 160rpx;
        z-index: 1000;

        .dropdown-item {
          display: block;
          width: 100%;
          padding: 24rpx 32rpx;
          border: none;
          background: none;
          font-size: 28rpx;
          color: #333;
          text-align: left;
          transition: all 0.3s;
      
      &:active {
            background: #f5f5f5;
          }
        }
      }
    }
  }
}

.image-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16rpx;
  width: 100%;
  box-sizing: border-box;
}

.image-item {
  position: relative;
  width: 100%;
  padding-bottom: 100%;
  border-radius: 16rpx;
  overflow: hidden;
  background: #f8f9fa;
  
  .preview-image {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}

.add-image {
  position: relative;
  width: 100%;
  padding-bottom: 100%;
  border-radius: 16rpx;
  border: 2rpx dashed #ff7e2d;
  background: #fff6ed;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s;
  
  &:active {
    transform: scale(0.98);
    background: darken(#fff6ed, 2%);
  }
  
  .add-icon {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 56rpx;
    color: #ff7e2d;
    font-weight: bold;
  }
}

.delete-btn {
  position: absolute;
  top: 8rpx;
  right: 8rpx;
  width: 40rpx;
  height: 40rpx;
  background: rgba(255, 62, 29, 0.9);
  color: #fff;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 28rpx;
  font-weight: bold;
  z-index: 2;
  transition: all 0.3s;
  
  &:active {
    transform: scale(0.9);
    background: darken(#ff3e1d, 5%);
  }
}

.required .label:after {
  content: '*';
  color: #ff7e2d;
  margin-left: 4rpx;
}

.date-picker-popup {
  background: #fff;
  border-radius: 24rpx 24rpx 0 0;
  overflow: hidden;
  
  .popup-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 24rpx;
    border-bottom: 1rpx solid #f5f5f5;
    
    .popup-title {
      font-size: 32rpx;
      font-weight: 600;
      color: #333;
    }
    
    .popup-close {
      font-size: 40rpx;
      color: #999;
      padding: 16rpx;
      margin: -16rpx;
      border-radius: 50%;
      
      &:active {
        background: #f5f5f5;
      }
    }
  }
  
  .picker-view {
    width: 100%;
    height: 400rpx;
    
    .picker-item {
      line-height: 88rpx;
      text-align: center;
      font-size: 32rpx;
      color: #333;
    }
  }
  
  .popup-footer {
    padding: 24rpx;
    border-top: 1rpx solid #f5f5f5;
    display: flex;
    gap: 16rpx;
    
    button {
      flex: 1;
      height: 88rpx;
      border: none;
      border-radius: 12rpx;
      font-size: 32rpx;
      font-weight: 500;
      
      &:active {
        transform: scale(0.98);
      }
    }
    
    .cancel-btn {
      background: #f5f5f5;
      color: #666;
      
      &:active {
        background: darken(#f5f5f5, 5%);
      }
    }
    
    .confirm-btn {
      background: #ff7e2d;
      color: #fff;
      
      &:active {
        background: darken(#ff7e2d, 5%);
      }
    }
  }
}

.notice-list {
  height: calc(100vh - 96rpx - 104rpx);
}

.view-popup {
  .popup-header {
    padding: 32rpx;
    border-bottom: 1rpx solid #f0f0f0;
    background: #fff;
    
    .popup-title {
      font-size: 36rpx;
      font-weight: 600;
      color: #333;
    }
  }

  .popup-content {
    max-height: 60vh;
    padding: 0;
    background: #fff;
  }

  .notice-detail {
    padding: 32rpx;

    .detail-header {
      margin-bottom: 32rpx;

      .detail-title {
        font-size: 40rpx;
        font-weight: 600;
        color: #333;
        line-height: 1.4;
        margin-bottom: 16rpx;
        display: block;
      }

      .detail-meta {
        display: flex;
        align-items: center;
        gap: 24rpx;
        font-size: 24rpx;
        color: #999;

        .detail-publisher {
          position: relative;
          padding-right: 24rpx;

          &::after {
            content: '';
            position: absolute;
            right: 0;
            top: 50%;
            transform: translateY(-50%);
            width: 2rpx;
            height: 24rpx;
            background: #eee;
          }
        }
      }
    }

    .detail-content {
      margin-bottom: 32rpx;

      .content-text {
        font-size: 28rpx;
        color: #666;
        line-height: 1.8;
        white-space: pre-wrap;
        word-break: break-all;
      }
    }

    .detail-images {
      .image-grid {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 16rpx;
        margin-top: 16rpx;

        .image-item {
          position: relative;
          width: 100%;
          padding-bottom: 100%;
          border-radius: 12rpx;
          overflow: hidden;
          background: #f8f9fa;

          .preview-image {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            object-fit: cover;
          }

          .delete-btn {
            position: absolute;
            top: 8rpx;
            right: 8rpx;
            width: 40rpx;
            height: 40rpx;
            background: rgba(0, 0, 0, 0.5);
            color: #fff;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 28rpx;
            font-weight: bold;
            z-index: 2;
            transition: all 0.3s;

            &:active {
              transform: scale(0.9);
              background: rgba(0, 0, 0, 0.7);
            }
          }
        }
      }
    }
  }

  .popup-footer {
    padding: 24rpx 32rpx;
    border-top: 1rpx solid #f0f0f0;
    background: #fff;
  }
}
  </style>    
